#include "socs/comm/types.h"
#include "socs/comm/socs.h"
#include "socs/comm/constants.h"
#include "socs/comm/config.h"
#include "socs/mod/hello.h"
#include "socs/mod/netlink.h"
#include "socs/mod/multicast.h"

static int recv_hello_basic(struct hello_packet *hello)
{
	return socs_neigh_recv_basic(hello);
}

int recv_hello(struct hello_packet *hello)
{
	int err;
	char csDomain[CSSIZE] = {};
	socs_config_get(ARGP_CSDOMAIN, csDomain);

	if (memcmp(hello->csDomain, csDomain, CSSIZE)) {
		log_debug("this packet is not for us");
		return -1;
	}

	log_debug("recv from neigh hello:opt=%d,vote_type=%d,csDomain=%s,data_len=%d",
			  hello->opt, hello->vote_type, hello->csDomain, hello->data_len);

	switch (hello->opt) {
	case HELLO_BASIC:
		err = recv_hello_basic(hello);
		break;

	default:
		log_err(ERR_UNKNOW_OPT, "hello->opt is unknow");
		return -1;
	}

	return err;
	return 0;
}

int send_hello_basic(struct localnode *lcn4, struct localnode *lcn6)
{
	struct hello_packet *hello;
	int len4 = 0, len6 = 0, len = 0;
	int err;
	char csDomain[CSSIZE] = {};

	if (!lcn4 && !lcn6) {
		log_debug("the localnode4 and localnode6 are null and no need to send ");
		return 0;
	} else if (!lcn6) { /*only the localnode4 is available*/
		len = len4 = SIZEOFLCN + SIZEOFLCL * (lcn4->lcl_num);
	} else if (!lcn4) { /*only the localnode6 is available*/
		len = len6 = SIZEOFLCN + SIZEOFLCL * (lcn6->lcl_num);
	} else {
		len4 = SIZEOFLCN + SIZEOFLCL * (lcn4->lcl_num);
		len6 = SIZEOFLCN + SIZEOFLCL * (lcn6->lcl_num);
		len = len4 + len6;
	}

	hello = (struct hello_packet *)kmalloc(len + sizeof(struct hello_packet),
										   GFP_ATOMIC);

	if (!hello) {
		log_err(ERR_ALLOC_FAILED, "%s kmalloc failed", __func__);
		return -1;
	}

	memset(hello, 0, len + sizeof(struct hello_packet));
	hello->opt = HELLO_BASIC;
	hello->vote_type = NOVOTE;
	hello->data_len = len;
	socs_config_get(ARGP_CSDOMAIN, csDomain);
	memcpy(hello->csDomain, csDomain, CSSIZE);

	if (!lcn6) {
		memcpy(hello->data, lcn4, len4);
	} else if (!lcn4) {
		memcpy(hello->data, lcn6, len6);
	} else {
		memcpy(hello->data, lcn4, len4);
		memcpy(hello->data + len4, lcn6, len6);
	}

	err = multicast_send(hello);

	if (err < 0) {
		log_err(ERR_MULSEND_FAILED, "%s multicast_send failed,err=%d", __func__, err);
		kfree(hello);
		return -1;
	}

	kfree(hello);
	return 0;
}



